package com.sky.controller.user;


import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.mapper.user.UserOrderMapper;
import com.sky.pojo.Orders;
import com.sky.properties.WeChatProperties;
import com.sky.service.user.UserOrderService;
import com.sky.webSocket.WebSocketServer;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.Map;

@RestController
//@RequestMapping
@Slf4j
public class PayController {
    @Autowired
    private WeChatProperties weChatProperties;
    @Autowired
    private UserOrderMapper orderMapper;
    @Autowired
    private UserOrderService orderService;
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 支付回调
     * @param responseObject
     * @return
     * @throws Exception
     */
    @PostMapping("/wxpay/notify")
    public String payNotify(@RequestBody JSONObject responseObject) throws Exception{
        log.info("收到微信支付成功回调");
        JSONObject resource = responseObject.getJSONObject("resource");
        String associated_data = (String)resource.get("associated_data");
        String ciphertext = (String)resource.get("ciphertext");
        String nonce = (String)resource.get("nonce");

        String key = weChatProperties.getApiV3Key();
        //解密结果
        String decryptData = new AesUtil(key.getBytes(StandardCharsets.UTF_8)).decryptToString(associated_data.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);

        log.info("解密结果：{}",decryptData);
        JSONObject decryptDataObj = JSONObject.parseObject(decryptData, JSONObject.class);
        //获取订单号
        String orderNo = (String)decryptDataObj.get("out_trade_no");
        log.info("订单号支付成功：{}",orderNo);
        //todo 调用支付成功业务处理逻辑
        orderService.success(orderNo);

        orderService.reminderNewOrder(orderNo);

        return "success";
    }

    /**
     * 微信支付
     * @param response
     * @param orderNo
     * @throws IOException
     */
    @GetMapping("/wxpay/orderPay")
    public void pay(HttpServletResponse response,String orderNo) throws IOException {
        //核心思想，通过http调用微信的native下单接口
        CloseableHttpClient client = createPayHttpClient();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");

        //通过订单号查询订单信息
        Orders orders = orderMapper.getByOrderNum(orderNo);
        //准备参数
        JSONObject param = new JSONObject();
        param.put("appid",weChatProperties.getPayAppid());
        param.put("mchid",weChatProperties.getMchid());
        param.put("description","订单号:"+orderNo);
        param.put("out_trade_no",orderNo.replace("-",""));
        param.put("notify_url",weChatProperties.getNotifyUrl());
        JSONObject amountJson = new JSONObject();
        amountJson.put("total",orders.getAmount().intValue());
        param.put("amount",amountJson);

        StringEntity stringEntity = new StringEntity(param.toJSONString(), "utf-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Accept","application/json");

        CloseableHttpResponse result = client.execute(httpPost);
        //处理结果，获取返回的链接
        String urlJson = EntityUtils.toString(result.getEntity());
        log.info("微信支付返回：{}",urlJson);
        Map map = JSONObject.parseObject(urlJson, Map.class);
        String codeUrl = (String) map.get("code_url");

        response.setContentType("image/png");
        QrCodeUtil.generate(codeUrl,500,500,"jpg",response.getOutputStream());
    }

    /**
     * 创建微信支付请求的HttpClient
     * @return
     * @throws UnsupportedEncodingException
     */
    private CloseableHttpClient createPayHttpClient() throws UnsupportedEncodingException {
        String privateKey = weChatProperties.getPrivateKey();
        String mchSerialNo = weChatProperties.getMchSerialNo();
        String mchId = weChatProperties.getMchid();
        String apiV3Key = weChatProperties.getApiV3Key();
        // 加载商户私钥（privateKey：私钥字符串）
        PrivateKey merchantPrivateKey = PemUtil
                .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3密钥）
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, merchantPrivateKey);
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(
                mchId, privateKeySigner);
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                wechatPay2Credentials, apiV3Key.getBytes("utf-8"));
        // 初始化httpClient
        return WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier))
                .build();
    }

    @GetMapping("/test")
    public void testPaySuccess(String orderNo){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type",1);
        jsonObject.put("orderId",orderNo);
        jsonObject.put("content","您有一条新的订单");
        webSocketServer.sendRemindMessage(jsonObject.toJSONString());
    }
}
